package erfgame.core.graphics.renderer.render;

import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Rectangle;
import java.awt.geom.AffineTransform;
import java.awt.geom.Point2D;
import java.awt.geom.Rectangle2D;

import org.apache.batik.bridge.BridgeContext;
import org.apache.batik.dom.svg.SVGOMSVGElement;
import org.apache.batik.gvt.GraphicsNode;
import org.w3c.dom.Document;
import org.w3c.dom.Element;

import erfgame.core.PointAndAngle;

public class BatikRender implements Render {
	
	public static Dimension getSize( Document svg ) {
	    SVGOMSVGElement element = (SVGOMSVGElement)svg.getDocumentElement();
	    int width = (int)Math.ceil(element.getWidth().getBaseVal().getValueInSpecifiedUnits());
	    int height = (int)Math.ceil(element.getHeight().getBaseVal().getValueInSpecifiedUnits());
	    return new Dimension( width, height );		
	}
	
	private Document svg;
	private GraphicsNode graphicsNode;
	private BridgeContext context;
	
	private float vx;
	private float vy;
	
	public BatikRender(Document svg, GraphicsNode graphicsNode, BridgeContext context) {
		this.svg = svg;
		this.graphicsNode = graphicsNode;
		this.context = context;

//		try {
//            Document document = DocumentBuilderFactory.newInstance().newDocumentBuilder().parse("../resource_default/src/main/resources/svg/sword.svg" );
//            GVTBuilder builder = new GVTBuilder();
//            this.graphicsNode =
//            builder.build(context,document);
//        } catch( Exception ex ) {
//            ex.printStackTrace();
//        }

        SVGOMSVGElement element = (SVGOMSVGElement)svg.getDocumentElement();
        vx = element.getViewBox().getBaseVal().getX();
        vy = element.getViewBox().getBaseVal().getY();
	}
	
	public Dimension getSize() {
		// TODO pass in from parent
		return getSize( svg );
//		Rectangle2D bounds = graphicsNode.getSensitiveBounds();
//		return new Dimension( 
//				(int)Math.ceil(bounds.getWidth()), 
//				(int)Math.ceil(bounds.getHeight())
//		);
	}
	
	public PointAndAngle getPoint(String id) {
		// look up the node with the id in the element
		Element node = svg.getElementById(id);
		PointAndAngle point;
		if( node != null ) {
			GraphicsNode gn = context.getGraphicsNode(node);
			if( gn != null ) {
				Rectangle2D bounds = gn.getBounds();
				
				int x = (int)Math.round(bounds.getCenterX() - vx);
				int y = (int)Math.round(bounds.getCenterY() - vy);
				double angle = getAngle( gn );
				
				point = new PointAndAngle(x, y, angle);
			} else {
				point = null;
			}
		} else {
			point = null;
		}
		return point;
	}
	
	private double getAngle( GraphicsNode gn ) {
		Point2D p = new Point2D.Double(1, 0);
		applyRotationsToPoint( gn, p );
		return Math.atan2( p.getY(), p.getX() );
	}
	
	private void applyRotationsToPoint( GraphicsNode gn, Point2D p ) {
		if( gn != null ) {
			AffineTransform transform = gn.getTransform();
			if( transform != null && (transform.getType() & AffineTransform.TYPE_GENERAL_ROTATION) != 0 ) {
				// NOTE: we are hoping it is only a rotate transform
				transform.transform(p, p);
			}
			applyRotationsToPoint(gn.getParent(), p );
		}
	}
	
	public void render(Graphics g, int x, int y) {
		Rectangle r = g.getClipBounds();
        g.setClip(0, 0, 1000, 1000);
        int dx = x;// + (int)vx;
        int dy = y;// + (int)vy;
        g.translate(dx, dy);
        graphicsNode.paint((Graphics2D)g);
        g.translate(-dx, -dy);
        if( r != null ) {
            g.setClip(r.x, r.y, r.width, r.height);
        }
	}

	public boolean contains(int lx, int ly) {
		return graphicsNode.contains( new Point2D.Float(lx, ly));
	}
	
	
}
